<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>

                    <h4>列表生成式</h4>
                    <div class="x-wiki-info"><span>2223次阅读</span></div>
                    <hr style="border-top-color:#ccc" />
                    <div class="x-wiki-content x-content"><p>列表生成式即List Comprehensions，是Python内置的非常简单却强大的可以用来创建list的生成式。</p>
<p>举个例子，要生成list <code>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]</code>可以用<code>range(1, 11)</code>：</p>
<pre><code>&gt;&gt;&gt; range(1, 11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
</code></pre><p>但如果要生成<code>[1x1, 2x2, 3x3, ..., 10x10]</code>怎么做？方法一是循环：</p>
<pre><code>&gt;&gt;&gt; L = []
&gt;&gt;&gt; for x in range(1, 11):
...    L.append(x * x)
...
&gt;&gt;&gt; L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
</code></pre><p>但是循环太繁琐，而列表生成式则可以用一行语句代替循环生成上面的list：</p>
<pre><code>&gt;&gt;&gt; [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
</code></pre><p>写列表生成式时，把要生成的元素<code>x * x</code>放到前面，后面跟<code>for</code>循环，就可以把list创建出来，十分有用，多写几次，很快就可以熟悉这种语法。</p>
<p>for循环后面还可以加上if判断，这样我们就可以筛选出仅偶数的平方：</p>
<pre><code>&gt;&gt;&gt; [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
</code></pre><p>还可以使用两层循环，可以生成全排列：</p>
<pre><code>&gt;&gt;&gt; [m + n for m in &#39;ABC&#39; for n in &#39;XYZ&#39;]
[&#39;AX&#39;, &#39;AY&#39;, &#39;AZ&#39;, &#39;BX&#39;, &#39;BY&#39;, &#39;BZ&#39;, &#39;CX&#39;, &#39;CY&#39;, &#39;CZ&#39;]
</code></pre><p>三层和三层以上的循环就很少用到了。</p>
<p>运用列表生成式，可以写出非常简洁的代码。例如，列出当前目录下的所有文件和目录名，可以通过一行代码实现：</p>
<pre><code>&gt;&gt;&gt; import os # 导入os模块，模块的概念后面讲到
&gt;&gt;&gt; [d for d in os.listdir(&#39;.&#39;)] # os.listdir可以列出文件和目录
[&#39;.emacs.d&#39;, &#39;.ssh&#39;, &#39;.Trash&#39;, &#39;Adlm&#39;, &#39;Applications&#39;, &#39;Desktop&#39;, &#39;Documents&#39;, &#39;Downloads&#39;, &#39;Library&#39;, &#39;Movies&#39;, &#39;Music&#39;, &#39;Pictures&#39;, &#39;Public&#39;, &#39;VirtualBox VMs&#39;, &#39;Workspace&#39;, &#39;XCode&#39;]
</code></pre><p><code>for</code>循环其实可以同时使用两个甚至多个变量，比如<code>dict</code>的<code>iteritems()</code>可以同时迭代key和value：</p>
<pre><code>&gt;&gt;&gt; d = {&#39;x&#39;: &#39;A&#39;, &#39;y&#39;: &#39;B&#39;, &#39;z&#39;: &#39;C&#39; }
&gt;&gt;&gt; for k, v in d.iteritems():
...     print k, &#39;=&#39;, v
... 
y = B
x = A
z = C
</code></pre><p>因此，列表生成式也可以使用两个变量来生成list：</p>
<pre><code>&gt;&gt;&gt; d = {&#39;x&#39;: &#39;A&#39;, &#39;y&#39;: &#39;B&#39;, &#39;z&#39;: &#39;C&#39; }
&gt;&gt;&gt; [k + &#39;=&#39; + v for k, v in d.iteritems()]
[&#39;y=B&#39;, &#39;x=A&#39;, &#39;z=C&#39;]
</code></pre><p>最后把一个list中所有的字符串变成小写：</p>
<pre><code>&gt;&gt;&gt; L = [&#39;Hello&#39;, &#39;World&#39;, &#39;IBM&#39;, &#39;Apple&#39;]
&gt;&gt;&gt; [s.lower() for s in L]
[&#39;hello&#39;, &#39;world&#39;, &#39;ibm&#39;, &#39;apple&#39;]
</code></pre><h3 id="-">小结</h3>
<p>运用列表生成式，可以快速生成list，可以通过一个list推导出另一个list，而代码却十分简洁。</p>
<p>思考：如果list中既包含字符串，又包含整数，由于非字符串类型没有<code>lower()</code>方法，所以列表生成式会报错：</p>
<pre><code>&gt;&gt;&gt; L = [&#39;Hello&#39;, &#39;World&#39;, 18, &#39;Apple&#39;, None]
&gt;&gt;&gt; [s.lower() for s in L]
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
AttributeError: &#39;int&#39; object has no attribute &#39;lower&#39;
</code></pre><p>使用内建的<code>isinstance</code>函数可以判断一个变量是不是字符串：</p>
<pre><code>&gt;&gt;&gt; x = &#39;abc&#39;
&gt;&gt;&gt; y = 123
&gt;&gt;&gt; isinstance(x, str)
True
&gt;&gt;&gt; isinstance(y, str)
False
</code></pre><p>请修改列表生成式，通过添加<code>if</code>语句保证列表生成式能正确地执行。</p>
</div>

                    <hr style="border-top-color:#ccc" />

                    